﻿/*
 * @Autor: PK
 * @Date: 2021/12/10 23:28:SS
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ShkSimulation.core.exceptions;
using ShkSimulation.core.template.model;

namespace ShkSimulation.core.dao.statistic {

	public class CommonProperty {

		private HashSet<string> doubleData = new HashSet<string>();
		private HashSet<string> hourCounterData = new HashSet<string>();

		public List<string/*VariableName*/> DoubleUniqueKeys => new List<string>(doubleData);
		
		public List<string/*VariableName*/> HourCounterUniqueKeys => new List<string>(hourCounterData);
		
		public CommonProperty(List<DataReporter> dataReporters) {
			if (dataReporters == null || dataReporters.Count == 0) {
				return;
			}
			var first = dataReporters.First();
			HashSet<string> doubleKeys = first.GetReportInfo().DoubleUniqueKeys;
			HashSet<string> hourCounterKeys = first.GetReportInfo().HourCounterUniqueKeys;
			HashSet<string> doubleKeysCompare = new HashSet<string>(doubleKeys);
			HashSet<string> hourCounterKeysCompare = new HashSet<string>(hourCounterKeys);
			foreach (var dataReporter in dataReporters) {
				var doubleUniqueKeys = dataReporter.GetReportInfo().DoubleUniqueKeys;
				var hourCounterUniqueKeys = dataReporter.GetReportInfo().HourCounterUniqueKeys;
				foreach (var key in doubleKeysCompare) {
					if (!doubleUniqueKeys.Contains(key)) {
						doubleKeys.Remove(key);
					}
				}
				foreach (var key in hourCounterKeysCompare) {
					if (!hourCounterUniqueKeys.Contains(key)) {
						hourCounterKeys.Remove(key);
					}
				}
			}
			this.doubleData = doubleKeys;
			this.hourCounterData = hourCounterKeys;
		}

	}

	public class DataReporterCollection : ICollection<DataReporter>, Unique {
		
		private List<DataReporter> dataReporters;
		private readonly string uniqueKey;

		public CommonProperty template;
		public CommonProperty Template {
			get {
				if (template == null) {
					template = new CommonProperty(dataReporters);
				}
				return template;
			}
		}

		public event Action<DataReporterCollection> OnReport = _ => { };

		public string Uniquekey => uniqueKey;

		public Dictionary<string, DataReportInfo> GetAllReportInfos() {
			return dataReporters.ToDictionary(each => each.Uniquekey, each => each.GetReportInfo());
		}

		public DataReporterCollection(string uniqueKey, List<DataReporter> reporters) {
			if (string.IsNullOrEmpty(uniqueKey) || reporters == null || reporters.Count == 0) {
				throw new SimulationInitException($"DataReporterCollection:[{uniqueKey}] Create failed");
			}
			this.uniqueKey = uniqueKey;
			this.dataReporters = reporters;
			foreach (var dataReporter in reporters) {
				dataReporter.ReportToCollection += (_) => {
					CurrentTriggerDataReporter = _;
					OnReport(this);
				};
			}
		}

		public static DataReporterCollection CreateByImplement<T>(T reporter) where T: DataReporter {
			List<DataReporter> result = new List<DataReporter>() {reporter};
			return new DataReporterCollection(reporter.Uniquekey, result);
		}

		public static DataReporterCollection CreateByImplements<T>(string uniqueKey, IEnumerable<T> reporters) where T: DataReporter {
			List<DataReporter> reporter = new List<DataReporter>();
			foreach (var dataReporter in reporters) {
				reporter.Add(dataReporter);
			}
			return new DataReporterCollection(uniqueKey, reporter);
		}

		public IEnumerator<DataReporter> GetEnumerator() {
			return dataReporters.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator() {
			return GetEnumerator();
		}

		public void Add(DataReporter item) {
			dataReporters.Add(item);
		}

		public void Clear() {
			dataReporters.Clear();
		}

		public bool Contains(DataReporter item) {
			return dataReporters.Contains(item);
		}

		public void CopyTo(DataReporter[] array, int arrayIndex) {
			dataReporters.CopyTo(array, arrayIndex);
		}

		public bool Remove(DataReporter item) {
			return dataReporters.Remove(item);
		}

		public int Count {
			get {
				return dataReporters.Count;
			}
		} 
		public bool IsReadOnly {
			get => false;
		}
		
		public DataReporter CurrentTriggerDataReporter { get; set; }
		
	}
}